package com.xiaoyu.lanling.feature.user

import `in`.srain.cube.request.JsonData
import `in`.srain.cube.util.LocalDisplay
import `in`.srain.cube.util.TimeUtils
import `in`.srain.cube.views.list.CubeRecyclerViewSimpleAdapter
import android.content.Context
import android.graphics.Color
import android.media.MediaPlayer
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.DecelerateInterpolator
import androidx.core.content.ContextCompat
import androidx.core.widget.NestedScrollView
import androidx.viewpager.widget.ViewPager
import com.github.florent37.viewanimator.ViewAnimator
import com.opensource.svgaplayer.SVGACallback
import com.opensource.svgaplayer.SVGADrawable
import com.qmuiteam.qmui.util.QMUIStatusBarHelper
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.event.AppEventBus
import com.xiaoyu.base.event.SimpleEventHandler
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.RxUtils
import com.xiaoyu.base.utils.extensions.dp
import com.xiaoyu.base.utils.extensions.getViewTag
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.base.utils.extensions.setViewTag
import com.xiaoyu.base.view.list.GridSpacingItemDecoration
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.activity.base.AppCompatToolbarActivity
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.data.SvgaData
import com.xiaoyu.lanling.event.charming.CharmingLevelUpEvent
import com.xiaoyu.lanling.event.coin.CoinAccostEvent
import com.xiaoyu.lanling.event.generosity.GenerosityLevelUpEvent
import com.xiaoyu.lanling.event.gift.GiveGiftAndSendMessageEvent
import com.xiaoyu.lanling.event.guard.GiveUpGuardEvent
import com.xiaoyu.lanling.event.user.*
import com.xiaoyu.lanling.feature.charming.MyCharmingLevelActivity
import com.xiaoyu.lanling.feature.coin.data.CoinData
import com.xiaoyu.lanling.feature.generosity.MyGenerosityLevelActivity
import com.xiaoyu.lanling.feature.gift.ChatGiftBottomSheetDialog
import com.xiaoyu.lanling.feature.gift.data.GiftData
import com.xiaoyu.lanling.feature.gift.model.Gift
import com.xiaoyu.lanling.feature.guard.fragment.GuardDetailDialogFragment
import com.xiaoyu.lanling.feature.profile.VerifyDialogManager
import com.xiaoyu.lanling.feature.profile.model.UserVoiceModel
import com.xiaoyu.lanling.feature.user.data.UserInfoData
import com.xiaoyu.lanling.feature.user.model.FeedImageItem
import com.xiaoyu.lanling.feature.user.model.GiftWallItem
import com.xiaoyu.lanling.feature.user.model.UserExtra.VerifyStatus.SUCCESS
import com.xiaoyu.lanling.feature.user.model.UserExtra.VerifyStatus.VERIFYING
import com.xiaoyu.lanling.feature.user.model.UserTag
import com.xiaoyu.lanling.feature.user.options.BlackAction
import com.xiaoyu.lanling.feature.user.options.MoreActionItemBase
import com.xiaoyu.lanling.feature.user.options.ReportAction
import com.xiaoyu.lanling.feature.user.options.SubscribeAction
import com.xiaoyu.lanling.feature.user.view.AlbumFragment
import com.xiaoyu.lanling.feature.user.viewholder.FeedOverviewViewHolder
import com.xiaoyu.lanling.feature.user.viewholder.GiftWallViewHolder
import com.xiaoyu.lanling.feature.user.viewholder.UserTagViewHolder
import com.xiaoyu.lanling.media.image.ImageLoadParam
import com.xiaoyu.lanling.media.image.ImageViewUtil
import com.xiaoyu.lanling.router.Router
import com.xiaoyu.lanling.util.MP3PlayerUtils
import com.xiaoyu.lanling.util.TextViewUtil
import com.xiaoyu.lanling.view.FragmentAdapter
import com.xiaoyu.lanling.view.MoreActionController
import com.xiaoyu.lanling.view.OnShowFragment
import com.xiaoyu.lanling.widget.svga.SvgaBaseCallback
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_user.*
import kotlinx.android.synthetic.main.toolbar_user.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.collections.ArrayList

class UserActivity : AppCompatToolbarActivity() {

    private val requestTag = Any()

    private val adapter = CubeRecyclerViewSimpleAdapter<UserTag>()
    private val feedImageAdapter = CubeRecyclerViewSimpleAdapter<FeedImageItem>()
    private val giftWallAdapter = CubeRecyclerViewSimpleAdapter<GiftWallItem>()
    private var mGiftAnimator: ViewAnimator? = null

    private var mUser: User? = null

    // the half rate of W:H
    private val verticalOffset: Float = (LocalDisplay.SCREEN_WIDTH_PIXELS / 1.125F / 2).toFloat()
    private var mVoicePlayerDisposable: Disposable? = null
    private var mViewPagerDisposable: Disposable? = null
    private var mSvgaDisposable: Disposable? = null
    private var isAutoPlay: Boolean = true
    private var isShowToolbarBackground = false
    private var isGiftAnimationPlaying: Boolean = false
    private var mSvgaAnimationDisposable: Disposable? = null
    private val mAnimationQueue: Queue<Gift> = LinkedList<Gift>()

    override fun onCreateSafelyAfterAppFinishInit(savedInstanceState: Bundle?) {
        super.onCreateSafelyAfterAppFinishInit(savedInstanceState)
        setTranslucent()
        setDarkStatusBar()
        setContentView(R.layout.activity_user)

        initAdapter()
        initBind()
        initEvent()
        initData()
    }

    override fun onStartSafelyAfterAppFinishInit(isFirstTimeStart: Boolean) {
        super.onStartSafelyAfterAppFinishInit(isFirstTimeStart)
        refreshHomePage()

        resumeVoice()
    }

    override fun onStop() {
        super.onStop()
        pauseVoice()
        clearGiftAnimation()
    }

    override fun onDestroy() {
        super.onDestroy()
        destroyVoice()
        RxUtils.disposable(mViewPagerDisposable, mSvgaDisposable)
    }

    private fun initAdapter() {
        adapter.setViewHolderClass(0, null, UserTagViewHolder::class.java, 20)
        user_tag_recyclerview.adapter = adapter
        feedImageAdapter.setViewHolderClass(0, null, FeedOverviewViewHolder::class.java, 20)
        feed_overview_recyclerview.adapter = feedImageAdapter
        giftWallAdapter.setViewHolderClass(0, null, GiftWallViewHolder::class.java, 10)
        gift_wall_recyclerview.addItemDecoration(GridSpacingItemDecoration(4, 8, false))
        gift_wall_recyclerview.adapter = giftWallAdapter
    }

    private fun initBind() {
        nested_scroll_view.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, _ ->
            when (scrollY.compareTo(verticalOffset)) {
                0 -> {
                    toolbar.setBackgroundColor(AppContext.getColor(R.color.cpColorWhite))
                    status_bar.setBackgroundColor(AppContext.getColor(R.color.cpColorWhite))
                }
                -1 -> {
                    val alpha = (255F * (scrollY / verticalOffset)).toInt()
                    val color = Color.argb(alpha, 255, 255, 255)
                    toolbar.setBackgroundColor(color)
                    status_bar.setBackgroundColor(color)
                }
            }

            if (scrollY < verticalOffset && isShowToolbarBackground) {
                toolbar_title.setTextColor(AppContext.getColor(R.color.colorPrimary))
                toolbar_more.setImageResource(R.drawable.icon_toolbar_action_more_dark)
                toolbar_edit.setTextColor(AppContext.getColor(R.color.colorPrimary))
                toolbar_back.setImageResource(R.drawable.icon_toolbar_action_back_dark)
                isShowToolbarBackground = false
                QMUIStatusBarHelper.setStatusBarDarkMode(this@UserActivity)
            } else if (scrollY >= verticalOffset && !isShowToolbarBackground) {
                toolbar_title.setTextColor(AppContext.getColor(R.color.colorOnPrimary))
                toolbar_more.setImageResource(R.drawable.icon_toolbar_action_more)
                toolbar_edit.setTextColor(AppContext.getColor(R.color.colorOnPrimary))
                toolbar_back.setImageResource(R.drawable.icon_toolbar_action_back)
                isShowToolbarBackground = true
                QMUIStatusBarHelper.setStatusBarLightMode(this@UserActivity)
            }
        })

        toolbar_back.setOnClickDebounceListener { finish() }
        toolbar_more.setOnClickDebounceListener {
            val user = mUser ?: return@setOnClickDebounceListener
            if (user.isSelf) {
                Router.instance.gotoUserProfileEditActivity(this, user)
            } else {
                showMoreActionList()
            }
        }
        toolbar_edit.setOnClickDebounceListener {
            val event = toolbar_more.getViewTag<UserHomePageEvent>()
                    ?: return@setOnClickDebounceListener
            Router.instance.gotoUserProfileEditActivity(this, event.user)
        }
        voice.setOnClickDebounceListener {
            val voiceModel = it.getViewTag<UserVoiceModel>() ?: return@setOnClickDebounceListener
            if (voiceModel.voiceUrl.isEmpty()) {
                return@setOnClickDebounceListener
            }
            playVoice(voiceModel)
        }
        guarder_avatar.setOnClickDebounceListener {
            val event = it.getViewTag<UserHomePageEvent>() ?: return@setOnClickDebounceListener
            GuardDetailDialogFragment.show(this.supportFragmentManager, event.user, event.guardInfo.user, event.guardInfo.needCoin, Constant.From.USER)
        }
        soliloquy.setOnClickDebounceListener {
            mUser?.let {
                Router.instance.gotoUserProfileEditActivity(this, it)
            }
        }
        basic_info_layout.setOnClickDebounceListener {
            mUser?.let {
                Router.instance.gotoUserProfileEditActivity(this, it)
            }
        }
        accost.setOnClickDebounceListener {
            mUser?.let {
                CoinData.accost(requestTag, it.uid)
            }
        }
        conversation.setOnClickDebounceListener {
            mUser?.let {
                Router.instance.gotoChatActivity(it.uid, "", "user")
            }
        }
        subscribe.setOnClickDebounceListener { v ->
            val subscribe = v.getViewTag<Boolean>() ?: return@setOnClickDebounceListener
            mUser?.let { user ->
                if (subscribe) {
                    ChatGiftBottomSheetDialog.show(supportFragmentManager, user, Constant.From.USER)
                } else {
                    UserInfoData.subscribeUser(requestTag, user.uid, true)
                }
            }
        }
        accost_svga.callback = object : SvgaBaseCallback() {
            override fun onFinished() {
                accost_svga.visibility = View.GONE
            }
        }
        moment_overview_layout.setOnClickDebounceListener {
            mUser?.let {
                Router.instance.gotoMyMomentActivity(this, it)
            }
        }
        charming_click_part.setOnClickListener {
            val isSelf = it.getViewTag<UserHomePageEvent>()?.user?.isSelf
                    ?: return@setOnClickListener
            if (isSelf) {
                Router.instance.simplyGoTo(this, MyCharmingLevelActivity::class.java)
            }
        }
        generosity_click_part.setOnClickListener {
            val isSelf = it.getViewTag<UserHomePageEvent>()?.user?.isSelf
                    ?: return@setOnClickListener
            if (isSelf) {
                Router.instance.simplyGoTo(this, MyGenerosityLevelActivity::class.java)
            }
        }
        svga_animation_view.callback = object : SVGACallback {
            override fun onPause() {
                clearGiftAnimation()
            }

            override fun onFinished() {
                svga_animation_view.visibility = View.GONE
                isGiftAnimationPlaying = false
                if (!mAnimationQueue.isEmpty()) {
                    playGiftAnimation(mAnimationQueue.poll())
                }
            }

            override fun onRepeat() {}
            override fun onStep(frame: Int, percentage: Double) {}
        }
    }

    private fun showMoreActionList() {
        val event = toolbar_more.getViewTag<UserHomePageEvent>() ?: return
        val list = mutableListOf<MoreActionItemBase>()
        list.add(BlackAction(this, requestTag, event.user.uid, event.black))
        list.add(ReportAction(this, event.user, "user"))

        subscribe.getViewTag<Boolean>()?.let {
            list.add(SubscribeAction(this, requestTag, event.user.uid, it))
        }
        MoreActionController.show(list)
    }

    private fun initEvent() {
        AppEventBus.bindContainerAndHandler(this, object : SimpleEventHandler() {
            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserHomePageEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                showData(event)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: CoinAccostEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                processAccost(event)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: SubscribeUserEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                updateSubscribe(event.subscribe)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: BlackUserEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                refreshHomePage()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserVoiceEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                updateVoice(event.voiceModel)
                playVoice(event.voiceModel)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: GiveGiftAndSendMessageEvent) {
                if (event.from != Constant.From.USER) {
                    return
                }
                enqueueOrPlayGiftAnimation(event.gift)
                refreshHomePage()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: GiveUpGuardEvent) {
                if (event.user != mUser) {
                    return
                }
                if (!event.result) {
                    return
                }
                refreshHomePage()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserMomentViewEvent) {
                feedImageAdapter.list = event.list
                feedImageAdapter.notifyDataSetChanged()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: CharmingLevelUpEvent) {
                refreshCharmingIcon(event.data.levelIcon.isEmpty(), event.data.levelIconLoadparam)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: GenerosityLevelUpEvent) {
                refreshGenerosityIcon(event.data.levelIcon.isEmpty(), event.data.levelIconLoadparam)
            }
        })
    }

    private fun enqueueOrPlayGiftAnimation(gift: Gift) {
        if (isGiftAnimationPlaying) {
            mAnimationQueue.offer(gift)
        } else {
            playGiftAnimation(gift)
        }
    }

    private fun playGiftAnimation(gift: Gift) {
        isGiftAnimationPlaying = true

        // If I'm an receiver, notice server that this gift has been played
        if (UserData.getInstance().isSelf(gift.toUid)) {
            GiftData.playGiftAnimation(gift.billId)
        }

        if (gift.hasSvga()) {
            RxUtils.disposable(mSvgaAnimationDisposable)
            mSvgaAnimationDisposable = SvgaData.createTaskFromAsset(gift.getSvgaFilename())
                    .compose(RxUtils.ioToMainSingleScheduler())
                    .subscribe({ entity ->
                        svga_animation_view.visibility = View.VISIBLE
                        svga_animation_view.setImageDrawable(SVGADrawable(entity))
                        svga_animation_view.startAnimation()
                    }, { t -> t.printStackTrace() })
        } else {
            mGiftAnimator = ViewAnimator.animate(animation_view)
                    .alpha(0F, 1F)
                    .scale(0F, 1F)
                    .dp().translationY(0F, 200F)
                    .interpolator(AccelerateDecelerateInterpolator())
                    .duration(1500)
                    .onStart {
                        ImageViewUtil.loadImage(animation_view, ImageLoadParam.newBuilder().setUrl(gift.icon).setSizeInDP(72).build())
                        animation_view.visibility = View.VISIBLE
                    }
                    .thenAnimate(animation_view)
                    .alpha(1F, 0F)
                    .scale(1F, 0F)
                    .dp().translationY(200F, 540F)
                    .interpolator(DecelerateInterpolator())
                    .duration(1800)
                    .onStop {
                        animation_view.visibility = View.GONE
                        isGiftAnimationPlaying = false

                        if (mAnimationQueue.isNotEmpty()) {
                            playGiftAnimation(mAnimationQueue.poll())
                        }
                    }
                    .start()
        }
    }

    private fun buildGiftAnimationImageLoadParam(gift: Gift): ImageLoadParam {
        val lowResLoadParam = ImageLoadParam.newBuilder()
                .setUrl(gift.icon)
                .setSizeInDP(60)
                .build()
        return ImageLoadParam.newBuilder()
                .setUrl(gift.icon)
                .setSizeInDP(72)
                .setLowResImageLoadParam(lowResLoadParam)
                .build()
    }

    private fun showData(event: UserHomePageEvent) {
        val hideBottomLayout = event.user.isSelf
        initAlbumViewPager(event)
        val isSystemAccount = UserData.getInstance().isSystemAccountUid(event.user.uid)
        ImageViewUtil.loadImage(vip_icon, event.vipInfo.imageLoadParam)
        if (event.user.isSelf) {
            user_moment_entry_title.text = AppContext.getString(R.string.moment_my_moment)
            generosity_arrow.visibility = View.VISIBLE
            charming_arrow.visibility = View.VISIBLE
        } else {
            generosity_arrow.visibility = View.INVISIBLE
            charming_arrow.visibility = View.INVISIBLE
        }
        toolbar_edit.visibility = if (event.user.isSelf) View.VISIBLE else View.GONE
        toolbar_more.visibility = if (isSystemAccount || event.user.isSelf) View.GONE else View.VISIBLE
        toolbar_more.setImageResource(if (event.user.isSelf) R.drawable.icon_user_info_eidt else R.drawable.icon_toolbar_action_more_dark)
        sex_and_age.setCompoundDrawablesRelativeWithIntrinsicBounds(if (event.user.isMale) R.drawable.user_sex_male_icon else R.drawable.user_sex_female_icon, 0, 0, 0)
        sex_and_age.background = ContextCompat.getDrawable(this, if (event.user.isMale) R.drawable.user_sex_male_background_shape else R.drawable.user_sex_female_background_shape)
        sex_and_age.text = event.age.toString()
        verify.visibility = if (isSystemAccount) View.GONE else View.VISIBLE
        updateVerify(event.user, event.verify)
        distance.visibility = if (event.user.isSelf || event.distance.isEmpty() || event.distance.toDouble() <= 0) View.GONE else View.VISIBLE
        distance.text = getString(R.string.user_distance_desc, event.distance)
        TextViewUtil.displayOrGone(soliloquy, event.soliloquy)
        TextViewUtil.displayOrGone(feed_count, event.feedCount)
        adapter.list = event.tags
        adapter.notifyDataSetChanged()
        feedImageAdapter.list = event.feedImages
        feedImageAdapter.notifyDataSetChanged()
        feed_overview_recyclerview.suppressLayout(true)
        nested_scroll_view.setPaddingRelative(0,0,0, if (isSystemAccount || hideBottomLayout) 0 else 56.dp.toInt())
        bottom_layout.visibility = if (isSystemAccount || hideBottomLayout) View.GONE else View.VISIBLE
        refreshCharmingIcon(event.charmingIcon.isEmpty(), event.charmingIconLoadParam)
        charming_num.text = AppContext.getString(R.string.charming_prefix, event.charmingNum)
        refreshGenerosityIcon(event.generosityIcon.isEmpty(), event.generosityIconLoadParam)
        generosity_num.text = AppContext.getString(R.string.generosity_prefix, event.generosityNum)
        ImageViewUtil.loadAvatarRoundWithBoard(guarder_avatar, event.guardInfo.user, 80, 2, R.color.user_info_avatar_border, false)
        ImageViewUtil.loadImage(guarder_level, ImageLoadParam.newBuilder().setUrl(event.guardInfo.levelIcon).setWidthInDP(106).setHeightInDP(40).build())
        gift_wall_layout.visibility = if (event.giftWallList.isNullOrEmpty()) View.GONE else View.VISIBLE
        gift_wall_title.text = getString(R.string.user_gift_wall_title, event.giftWallList.size.toString())
        giftWallAdapter.list = event.giftWallList
        giftWallAdapter.notifyDataSetChanged()

        if (!hideBottomLayout) {
            updateSubscribe(event.subscribe)
        }
        toolbar_more.setViewTag(event)
        toolbar_edit.setViewTag(event)
        guarder_avatar.setViewTag(event)
        charming_click_part.setViewTag(event)
        generosity_click_part.setViewTag(event)
    }

    private fun refreshGenerosityIcon(newBee: Boolean, generosityIconLoadParam: ImageLoadParam?) {
        if (newBee) {
            generosity_icon.visibility = View.GONE
        } else {
            generosity_icon.visibility = View.VISIBLE
            ImageViewUtil.loadImage(generosity_icon, generosityIconLoadParam)
        }
    }

    private fun refreshCharmingIcon(zeroValue: Boolean, charmingIconLoadParam: ImageLoadParam?) {
        if (zeroValue) {
            charming_icon.visibility = View.GONE
        } else {
            charming_icon.visibility = View.VISIBLE
            ImageViewUtil.loadImage(charming_icon, charmingIconLoadParam)
        }
    }

    private fun initAlbumViewPager(event: UserHomePageEvent) {
        val originalUrls = ArrayList<String>().apply {
            add(event.user.avatar)
            addAll(event.photos)
        }
        val recyclerUrls = getRecyclerUrl(originalUrls)

        val titles = mutableListOf<CharSequence>()
        val fragments = ArrayList<OnShowFragment>()

        recyclerUrls.forEachIndexed { index, url ->
            titles.add(index.toString())
            fragments.add(AlbumFragment.create(url, originalUrls))
        }

        val originalUrlCount = originalUrls.size

        val fragmentAdapter = FragmentAdapter(supportFragmentManager, fragments, titles)
        album_view_pager.adapter = fragmentAdapter
        album_view_pager.offscreenPageLimit = fragments.size
        album_view_pager.currentItem = 1
        album_view_pager.setPagingEnabled(originalUrlCount > 1)
        album_view_pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
            override fun onPageSelected(position: Int) {
                var realPosition = position
                if (position == 0) {
                    realPosition = fragments.size - 2
                } else if (position == fragments.size - 1) {
                    realPosition = 1
                }
                view_pager_indicator.text = getString(R.string.user_view_pager_indicator, (realPosition).toString(), originalUrlCount.toString())
                fragmentAdapter.tryShowOnIndex(position)
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                if (positionOffset == 0f) {
                    if (position == fragments.size - 1) {
                        album_view_pager.setCurrentItem(1, false)
                    } else if (position == 0) {
                        album_view_pager.setCurrentItem(fragments.size - 2, false)
                    }
                }
            }

            override fun onPageScrollStateChanged(state: Int) {
                when (state) {
                    ViewPager.SCROLL_STATE_IDLE -> isAutoPlay = true
                    ViewPager.SCROLL_STATE_DRAGGING -> isAutoPlay = false
                    ViewPager.SCROLL_STATE_SETTLING -> isAutoPlay = true
                }
            }
        })

        isAutoPlay = originalUrls.size >= 2
        view_pager_indicator.text = getString(R.string.user_view_pager_indicator, (album_view_pager.currentItem).toString(), originalUrlCount.toString())
        initViewPagerDisposable()
    }

    private fun getRecyclerUrl(urls: MutableList<String>): MutableList<String> {
        val recyclerUrls = mutableListOf<String>()
        recyclerUrls.addAll(urls)
        recyclerUrls.add(0, recyclerUrls.last())
        recyclerUrls.add(recyclerUrls.size - 1, recyclerUrls.first())
        return recyclerUrls
    }

    private fun initViewPagerDisposable() {
        RxUtils.disposable(mViewPagerDisposable)
        mViewPagerDisposable = Flowable.interval((3 * TimeUtils.MILLIS_IN_SECOND), TimeUnit.MILLISECONDS)
                .onBackpressureDrop()
                .compose(RxUtils.ioToMainFlowableScheduler())
                .filter {
                    album_view_pager?.let {
                        return@filter isAutoPlay && it.childCount > 0
                    }
                    return@filter false
                }
                .subscribe({
                    album_view_pager?.let {
                        it.currentItem = (it.currentItem + 1) % it.childCount
                    }
                }, { it.printStackTrace() })
    }

    private fun updateSubscribe(subscribed: Boolean) {
        subscribe.isSelected = subscribed
        subscribe.setText(if (subscribed) R.string.user_bottom_gift else R.string.user_bottom_subscribe)
        subscribe.setViewTag(subscribed)
    }

    private fun updateVerify(user: User, status: String) {
        when (status) {
            SUCCESS -> {
                verify.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_verify_verified, 0, 0, 0)
                verify.isEnabled = false
                verify_tip.visibility = View.GONE
            }
            VERIFYING -> {
                verify.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_verify_unverified, 0, 0, 0)
                verify.isEnabled = false
                verify_tip.visibility = View.GONE
            }
            else -> {
                verify.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_verify_unverified, 0, 0, 0)
                verify.isEnabled = user.isSelf
                verify_tip.visibility = if (user.isSelf) View.VISIBLE else View.GONE
                if (user.isSelf) {
                    setOnClickForSelf()
                }
            }
        }
    }

    private fun setOnClickForSelf() {
        verify.setOnClickDebounceListener {
            Router.instance.gotoVerifyHumanActivity(this)
        }
        verify_tip.setOnClickDebounceListener {
            Router.instance.gotoVerifyHumanActivity(this)
        }
    }

    private fun initData() {
        val uidString = intent.getStringExtra(Constant.IntentKey.KEY_UID)
        val uid = if (TextUtils.isEmpty(uidString)) null else uidString
        // may user not passed instead uid  passed ,so we construct a user
        mUser = intent.getSerializableExtra(Constant.IntentKey.KEY_USER) as? User
                ?: User.fromJson(JsonData.newMap())
        uid?.let {
            mUser?.uid = uid
        }

        id.text = getString(R.string.user_id_title, mUser?.uid)
        name.text = mUser?.remark

        val isSelf = mUser?.isSelf == true
        soliloquy.isEnabled = isSelf

        mUser?.let {
            UserInfoData.getVoice(requestTag, it.uid)
        }
    }

    private fun refreshHomePage() {
        mUser?.let {
            UserInfoData.homePage(requestTag, it.uid)
        }
    }

    private fun showAccostSvga() {
        mSvgaDisposable?.dispose()
        mSvgaDisposable = SvgaData.createTaskFromAsset("accost.svga")
                .compose(RxUtils.ioToMainSingleScheduler())
                .subscribe({ entity ->
                    accost_svga.visibility = View.VISIBLE
                    val drawable = SVGADrawable(entity)
                    accost_svga.setImageDrawable(drawable)
                    accost_svga.loops = 1
                    accost_svga.startAnimation()
                    mSvgaDisposable?.dispose()
                }, { t -> t.printStackTrace() })
    }

    private fun updateVoice(voiceModel: UserVoiceModel) {
        when (voiceModel.verifyStatus) {
            UserVoiceModel.VERIFYING -> {
                voice.visibility = View.VISIBLE
                voice.setText(R.string.user_profile_voice_verifying)
                voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_verifying, 0, 0, 0)
            }
            else -> {
                if (voiceModel.voiceUrl.isEmpty()) {
                    voice.visibility = View.GONE
                } else {
                    voice.visibility = View.VISIBLE
                    voice.text = getString(R.string.user_profile_voice_success, voiceModel.duration.toString())
                    voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_success, 0, 0, 0)
                }
            }
        }
        voice.setViewTag(voiceModel)
    }

    private fun playVoice(voiceModel: UserVoiceModel) {
        if (MP3PlayerUtils.getInstance().isPlaying) {
            pauseVoice()
        } else if (!MP3PlayerUtils.getInstance().isPlaying && MP3PlayerUtils.getInstance().isSamePath(voiceModel.voiceUrl)) {
            resumeVoice()
        } else {
            MP3PlayerUtils.getInstance().start(voiceModel.voiceUrl, object : MP3PlayerUtils.OnStatusListener {
                override fun OnPlaying(mp: MediaPlayer?) {
                }

                override fun OnError(what: String?, extra: String?) {
                    voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_success, 0, 0, 0)
                    mVoicePlayerDisposable?.dispose()
                }

                override fun onCompletion(mp: MediaPlayer?) {
                    mp?.let {
                        voice.text = getString(R.string.user_profile_voice_success, (it.duration / 1000).toString())
                    }
                    voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_success, 0, 0, 0)
                    mVoicePlayerDisposable?.dispose()
                }

                override fun OnPrepared(mp: MediaPlayer?) {
                    updatePlayLayout()
                }
            })
        }
    }

    private fun updatePlayLayout() {
        voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_playing, 0, 0, 0)
        mVoicePlayerDisposable?.dispose()
        mVoicePlayerDisposable = Observable.interval(0, 1000L, TimeUnit.MILLISECONDS)
                .compose(RxUtils.ioToMainObservableScheduler())
                .subscribe({
                    val remainSec = (MP3PlayerUtils.getInstance().duration - MP3PlayerUtils.getInstance().currentPosition) / 1000
                    voice.text = getString(R.string.user_profile_voice_success, remainSec.toString())
                }, { t -> t.printStackTrace() })
    }

    private fun pauseVoice() {
        mVoicePlayerDisposable?.dispose()
        voice?.getViewTag<UserVoiceModel>()?.let {
            val playing = MP3PlayerUtils.getInstance().isPlaying(it.voiceUrl)
            if (playing) {
                MP3PlayerUtils.getInstance().pause()
            }
        }
        voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_voice_success, 0, 0, 0)
    }

    private fun destroyVoice() {
        mVoicePlayerDisposable?.dispose()
        voice.getViewTag<UserVoiceModel>()?.let {
            val isSamePath = MP3PlayerUtils.getInstance().isSamePath(it.voiceUrl)
            if (isSamePath) {
                MP3PlayerUtils.getInstance().release()
            }
        }
    }

    private fun resumeVoice() {
        voice.getViewTag<UserVoiceModel>()?.let {
            val isSamePath = MP3PlayerUtils.getInstance().isSamePath(it.voiceUrl)
            if (isSamePath) {
                MP3PlayerUtils.getInstance().resume()
                updatePlayLayout()
            }
        }
    }

    private fun processAccost(event: CoinAccostEvent) {
        showAccostSvga()

        if (event.showVerifyAndVoiceDialog) {
            VerifyDialogManager.showDialog()
        }
    }

    private fun clearGiftAnimation() {
        mAnimationQueue.clear()
        svga_animation_view.visibility = View.GONE
        svga_animation_view.stopAnimation()
        mSvgaAnimationDisposable?.dispose()
        mGiftAnimator?.cancel()
        isGiftAnimationPlaying = false
        animation_view.visibility = View.GONE
    }
}